package com.qdxht.dispenser.ui.activity;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ScrollView;

import com.qdxht.dispenser.base.BaseActivity;
import com.qdxht.dispenser.databinding.ActivitySerialPortTestBinding;
import com.qdxht.dispenser.service.SerialPortService;
import com.qdxht.dispenser.service.SerialPortServiceHelper;
import com.qdxht.dispenser.utils.SerialProtocolUtil;
import com.qdxht.dispenser.utils.SerialProtocolUtil.ProtocolResult;
import com.hjq.toast.ToastUtils;
import com.vi.vioserial.COMSerial;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import timber.log.Timber;

/**
 * 串口通信测试页面
 * 使用SerialPortService进行串口操作
 */
public class SerialPortTestActivity extends BaseActivity<ActivitySerialPortTestBinding> 
        implements SerialPortService.OnSerialDataListener, 
                   SerialPortService.OnSerialStatusListener,
                   SerialPortServiceHelper.ServiceConnectionCallback {

    private static final String TAG = "SerialPortTest";
    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());

    private List<String> mPortList = new ArrayList<>();
    private String currentPort;
    private int currentBaudRate = 9600;
    private final int[] baudRates = {4800, 9600, 19200, 38400, 57600, 115200};
    private int deviceAddress = 1; // 默认设备地址

    // 添加日志类型常量
    private static final int LOG_TYPE_INFO = 0;
    private static final int LOG_TYPE_SEND = 1;
    private static final int LOG_TYPE_RECEIVE = 2;
    private static final int LOG_TYPE_ERROR = 3;
    
    // 串口服务帮助类
    private SerialPortServiceHelper serviceHelper;
    // 串口服务
    private SerialPortService serialPortService;

    public static void start(Context context) {
        Intent intent = new Intent(context, SerialPortTestActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected ActivitySerialPortTestBinding getBinding() {
        return ActivitySerialPortTestBinding.inflate(getLayoutInflater());
    }

    @Override
    protected void initView() {
        // 设置标题
        binding.titleBar.setTitle("串口通信测试");

        // 初始化串口列表
        initSerialPortSpinner();

        // 初始化波特率选项
        initBaudRateSpinner();

        // 设置按钮点击事件
        initClickListeners();
        
        // 初始化串口服务
        serviceHelper = new SerialPortServiceHelper(this, this);
        // 将生命周期观察者添加到Activity的生命周期中
        getLifecycle().addObserver(serviceHelper);
    }

    @Override
    protected void initData() {
        // 服务绑定后会在onServiceConnected回调中初始化
    }

    private void initSerialPortSpinner() {
        android.serialport.SerialPortFinder serialPortFinder = new android.serialport.SerialPortFinder();
        String[] allDevicesPath = serialPortFinder.getAllDevicesPath();
        if (allDevicesPath != null && allDevicesPath.length > 0) {
            for (String path : allDevicesPath) {
                if (path.contains("ttyS")) {
                    mPortList.add(path);
                }
            }
        }
        
        if (mPortList.isEmpty()) {
            addLog("未找到ttyS串口设备", LOG_TYPE_ERROR);
            ToastUtils.show("未找到串口设备");
        }
        
        ArrayAdapter<String> portAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, mPortList);
        portAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        binding.spinnerPort.setAdapter(portAdapter);
        
        binding.spinnerPort.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                currentPort = mPortList.get(position);
                addLog("选择串口: " + currentPort);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });

        if (mPortList.size() > 0) {
            currentPort = mPortList.get(0);
        }
    }

    private void initBaudRateSpinner() {
        List<String> baudRateList = new ArrayList<>();
        for (int rate : baudRates) {
            baudRateList.add(String.valueOf(rate));
        }

        ArrayAdapter<String> baudRateAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, baudRateList);
        baudRateAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        binding.spinnerBaudRate.setAdapter(baudRateAdapter);

        binding.spinnerBaudRate.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                currentBaudRate = baudRates[position];
                addLog("选择波特率: " + currentBaudRate);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {}
        });

        // 默认选择9600
        for (int i = 0; i < baudRates.length; i++) {
            if (baudRates[i] == 9600) {
                binding.spinnerBaudRate.setSelection(i);
                break;
            }
        }
    }

    private void initClickListeners() {
        // 基本串口操作
        binding.btnOpen.setOnClickListener(v -> openSerialPort());
        binding.btnClose.setOnClickListener(v -> closeSerialPort());
        binding.btnSend.setOnClickListener(v -> sendData());
        binding.btnClearLog.setOnClickListener(v -> {
            binding.tvLogs.setText("");
            addLog("日志已清除", LOG_TYPE_INFO);
        });
        
        // 读传感器状态
        binding.btnReadSideSensor.setOnClickListener(v -> sendReadSensor(0x01));
        binding.btnReadMiddleSensor.setOnClickListener(v -> sendReadSensor(0x02));
        binding.btnReadJamStatus.setOnClickListener(v -> sendReadSensor(0x04));
        binding.btnReadAllErrors.setOnClickListener(v -> sendReadSensor(0x05));
        
        // 写配置参数
        binding.btnWriteBaudRate.setOnClickListener(v -> sendWriteConfig(0x01));
        binding.btnWriteTicketCount.setOnClickListener(v -> sendWriteConfig(0x05));
        binding.btnWriteDispenseSpeed.setOnClickListener(v -> sendWriteConfig(0x08));
        
        // 读配置参数
        binding.btnReadBaudRate.setOnClickListener(v -> sendReadConfig(0x01));
        binding.btnReadDispenseCount.setOnClickListener(v -> sendReadConfig(0x03));
        binding.btnReadPaperDistance.setOnClickListener(v -> sendReadConfig(0x04));
        binding.btnReadRemainingTickets.setOnClickListener(v -> sendReadConfig(0x05));
        binding.btnReadFirmware.setOnClickListener(v -> sendReadConfig(0x06));
        binding.btnReadDeviceModel.setOnClickListener(v -> sendReadConfig(0x07));
        binding.btnReadDispenseSpeed.setOnClickListener(v -> sendReadConfig(0x08));
        
        // 发袋命令
        binding.btnDispenseInch.setOnClickListener(v -> sendDispenseCommand(0x01));
        binding.btnDispenseCm.setOnClickListener(v -> sendDispenseCommand(0x02));
        
        // 错误恢复
        binding.btnRecoverJam.setOnClickListener(v -> sendErrorRecovery());
        
        // 自动扫描
        binding.btnAutoScan.setOnClickListener(v -> autoScanPort());
    }

    /**
     * 自动扫描串口设备
     */
    private void autoScanPort() {
        if (!checkServiceAvailable()) {
            return;
        }
        
        addLog("开始自动扫描串口设备...", LOG_TYPE_INFO);
        serialPortService.scanAndConnectPort(new SerialPortService.OnSerialFindListener() {
            @Override
            public void onFind(String port, byte address) {
                addLog("成功连接串口: " + port + ", 地址: " + String.format("%02X", address), LOG_TYPE_INFO);
                // 更新UI
                for (int i = 0; i < mPortList.size(); i++) {
                    if (mPortList.get(i).equals(port)) {
                        binding.spinnerPort.setSelection(i);
                        break;
                    }
                }
                binding.etDeviceAddress.setText(String.format("%X", address));
            }
        });
    }

    /**
     * 读取设备地址
     */
    private int getDeviceAddress() {
        try {
            String addressHex = binding.etDeviceAddress.getText().toString().trim();
            if (!TextUtils.isEmpty(addressHex)) {
                int address = Integer.parseInt(addressHex, 16);
                if (address >= 0 && address <= 0x0F) {
                    return address;
                }
            }
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "解析设备地址错误");
        }
        ToastUtils.show("设备地址格式错误，使用默认地址01");
        return 1; // 默认地址
    }

    /**
     * 发送读传感器状态指令
     */
    private void sendReadSensor(int sensorType) {
        if (!checkServiceAvailable() || !checkSerialPortOpen()) {
            return;
        }
        deviceAddress = getDeviceAddress();
        serialPortService.setCurrentDeviceAddress((byte) deviceAddress);
        addLog("发送读传感器状态命令，类型: " + sensorType + ", 设备地址: " + String.format("%02X", deviceAddress), LOG_TYPE_INFO);
        serialPortService.sendReadSensorWithResult(sensorType, (success, msg, result) -> {
            addLog("读传感器命令执行结果: " + (success ? "成功" : "失败") + ", " + msg + (result != null ? ("\n解析: " + result.toString()) : ""), success ? LOG_TYPE_INFO : LOG_TYPE_ERROR);
        });
    }
    
    /**
     * 发送写配置参数指令
     */
    private void sendWriteConfig(int configType) {
        if (!checkServiceAvailable() || !checkSerialPortOpen()) {
            return;
        }
        deviceAddress = getDeviceAddress();
        serialPortService.setCurrentDeviceAddress((byte) deviceAddress);
        String configValue = binding.etConfigValue.getText().toString().trim();
        if (TextUtils.isEmpty(configValue)) {
            ToastUtils.show("请输入配置值");
            return;
        }
        boolean isHexFormat = binding.rbConfigHex.isChecked();
        String hexConfigValue;
        try {
            if (isHexFormat) {
                hexConfigValue = configValue;
                if (hexConfigValue.length() % 2 != 0) {
                    hexConfigValue = "0" + hexConfigValue;
                }
            } else {
                int decValue = Integer.parseInt(configValue);
                hexConfigValue = Integer.toHexString(decValue);
                if (hexConfigValue.length() % 2 != 0) {
                    hexConfigValue = "0" + hexConfigValue;
                }
            }
            addLog("发送写配置参数命令，类型: " + configType + ", 值: " + hexConfigValue + ", 设备地址: " + String.format("%02X", deviceAddress), LOG_TYPE_INFO);
            serialPortService.sendWriteConfigWithResult(configType, hexConfigValue, (success, msg, result) -> {
                addLog("写配置命令执行结果: " + (success ? "成功" : "失败") + ", " + msg + (result != null ? ("\n解析: " + result.toString()) : ""), success ? LOG_TYPE_INFO : LOG_TYPE_ERROR);
            });
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "配置值解析错误");
            ToastUtils.show("配置值格式错误");
        }
    }
    
    /**
     * 发送读配置参数指令
     */
    private void sendReadConfig(int configType) {
        if (!checkServiceAvailable() || !checkSerialPortOpen()) {
            return;
        }
        deviceAddress = getDeviceAddress();
        serialPortService.setCurrentDeviceAddress((byte) deviceAddress);
        addLog("发送读配置参数命令，类型: " + configType + ", 设备地址: " + String.format("%02X", deviceAddress), LOG_TYPE_INFO);
        serialPortService.sendReadConfigWithResult(configType, (success, msg, result) -> {
            addLog("读配置命令执行结果: " + (success ? "成功" : "失败") + ", " + msg + (result != null ? ("\n解析: " + result.toString()) : ""), success ? LOG_TYPE_INFO : LOG_TYPE_ERROR);
        });
    }
    
    /**
     * 发送发袋命令
     */
    private void sendDispenseCommand(int type) {
        if (!checkServiceAvailable() || !checkSerialPortOpen()) {
            return;
        }
        deviceAddress = getDeviceAddress();
        serialPortService.setCurrentDeviceAddress((byte) deviceAddress);
        String lengthValue = binding.etDispenseLength.getText().toString().trim();
        if (TextUtils.isEmpty(lengthValue)) {
            ToastUtils.show("请输入发袋长度");
            return;
        }
        boolean isHexFormat = false;
        String hexLengthValue;
        try {
            if (isHexFormat) {
                hexLengthValue = lengthValue;
                if (hexLengthValue.length() % 2 != 0) {
                    hexLengthValue = "0" + hexLengthValue;
                }
            } else {
                int decValue = Integer.parseInt(lengthValue);
                hexLengthValue = Integer.toHexString(decValue);
                if (hexLengthValue.length() % 2 != 0) {
                    hexLengthValue = "0" + hexLengthValue;
                }
            }
            String lengthType = (type == 0x01) ? "按寸" : "按厘米";
            addLog("发送" + lengthType + "发袋命令，长度: " + hexLengthValue + ", 设备地址: " + String.format("%02X", deviceAddress), LOG_TYPE_INFO);
            serialPortService.sendDispenseWithResult(type, hexLengthValue, (success, msg, result) -> {
                addLog("发袋命令执行结果: " + (success ? "成功" : "失败") + ", " + msg + (result != null ? ("\n解析: " + result.toString()) : ""), success ? LOG_TYPE_INFO : LOG_TYPE_ERROR);
            });
        } catch (Exception e) {
            Timber.tag(TAG).e(e, "发袋长度解析错误");
            ToastUtils.show("发袋长度格式错误");
        }
    }
    
    /**
     * 发送错误恢复命令
     */
    private void sendErrorRecovery() {
        if (!checkServiceAvailable() || !checkSerialPortOpen()) {
            return;
        }
        deviceAddress = getDeviceAddress();
        serialPortService.setCurrentDeviceAddress((byte) deviceAddress);
        addLog("发送错误恢复命令, 设备地址: " + String.format("%02X", deviceAddress), LOG_TYPE_INFO);
        serialPortService.sendErrorRecoveryWithResult(2, (success, msg, result) -> {
            addLog("错误恢复命令执行结果: " + (success ? "成功" : "失败") + ", " + msg + (result != null ? ("\n解析: " + result.toString()) : ""), success ? LOG_TYPE_INFO : LOG_TYPE_ERROR);
        });
    }

    /**
     * 检查服务是否可用
     */
    private boolean checkServiceAvailable() {
        if (serialPortService == null) {
            ToastUtils.show("串口服务未连接");
            return false;
        }
        return true;
    }

    /**
     * 检查串口是否打开
     */
    private boolean checkSerialPortOpen() {
        if (serialPortService == null) {
            ToastUtils.show("串口服务未连接");
            return false;
        }
        
        if (serialPortService.getCurrentPortPath() == null) {
            ToastUtils.show("串口未打开");
            return false;
        }
        
        return true;
    }

    /**
     * 打开串口
     */
    private void openSerialPort() {
        if (!checkServiceAvailable()) {
            return;
        }
        
        if (TextUtils.isEmpty(currentPort)) {
            ToastUtils.show("请选择串口");
            return;
        }
        
        addLog("正在打开串口: " + currentPort + ", 波特率: " + currentBaudRate, LOG_TYPE_INFO);
        
        deviceAddress = getDeviceAddress(); // 更新当前设备地址
        
        // 打开串口
        boolean success = serialPortService.connect(currentPort, currentBaudRate);
        if (success) {
            serialPortService.setCurrentDeviceAddress((byte) deviceAddress);
            addLog("串口打开成功", LOG_TYPE_INFO);
        } else {
            addLog("串口打开失败", LOG_TYPE_ERROR);
        }
    }

    /**
     * 关闭串口
     */
    private void closeSerialPort() {
        if (!checkServiceAvailable()) {
            return;
        }
        
        serialPortService.disconnect();
        addLog("串口已关闭", LOG_TYPE_INFO);
    }

    /**
     * 发送自定义数据
     */
    private void sendData() {
        if (!checkServiceAvailable() || !checkSerialPortOpen()) {
            return;
        }
    }

    /**
     * 添加日志
     */
    private void addLog(String log, int type) {
        runOnUiThread(() -> {
            String time = TIME_FORMAT.format(new Date());
            String prefix;
            String colorStart;
            String colorEnd = "";

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                switch (type) {
                    case LOG_TYPE_INFO:
                        prefix = "[信息]";
                        colorStart = "<font color='#808080'>"; // 灰色
                        break;
                    case LOG_TYPE_SEND:
                        prefix = "[发送]";
                        colorStart = "<font color='#2196F3'>"; // 蓝色
                        break;
                    case LOG_TYPE_RECEIVE:
                        prefix = "[接收]";
                        colorStart = "<font color='#4CAF50'>"; // 绿色
                        break;
                    case LOG_TYPE_ERROR:
                        prefix = "[错误]";
                        colorStart = "<font color='#F44336'>"; // 红色
                        break;
                    default:
                        prefix = "[信息]";
                        colorStart = "<font color='#808080'>";
                }
                colorEnd = "</font>";
                
                String formatted = colorStart + time + " " + prefix + " " + log + colorEnd + "<br/>";
                String currentLogs = binding.tvLogs.getText().toString();
                binding.tvLogs.setText(Html.fromHtml(formatted + currentLogs, Html.FROM_HTML_MODE_COMPACT));
            } else {
                switch (type) {
                    case LOG_TYPE_INFO:
                        prefix = "[信息]";
                        break;
                    case LOG_TYPE_SEND:
                        prefix = "[发送]";
                        break;
                    case LOG_TYPE_RECEIVE:
                        prefix = "[接收]";
                        break;
                    case LOG_TYPE_ERROR:
                        prefix = "[错误]";
                        break;
                    default:
                        prefix = "[信息]";
                }
                
                String formatted = time + " " + prefix + " " + log + "\n";
                binding.tvLogs.setText(formatted + binding.tvLogs.getText());
            }
            
            // 自动滚动到顶部
            binding.scrollView.fullScroll(ScrollView.FOCUS_UP);
        });
    }

    /**
     * 添加普通日志
     */
    private void addLog(String log) {
        addLog(log, LOG_TYPE_INFO);
    }

    // SerialPortService.OnSerialDataListener 接口实现
    @Override
    public void onDataReceived(String port, String hexData, ProtocolResult result) {
        String message = "接收数据: " + SerialProtocolUtil.formatHexString(hexData);
        if (result != null && result.isSuccess()) {
            message += "\n解析结果: " + result.toString();
        }
        addLog(message, LOG_TYPE_RECEIVE);
    }

    // SerialPortService.OnSerialStatusListener 接口实现
    @Override
    public void onStatusChanged(SerialPortService.SerialStatus status) {
        addLog("串口状态变化: " + status.getDescription(), LOG_TYPE_INFO);
        
        // 如果连接成功，更新UI
        if (status == SerialPortService.SerialStatus.CONNECTED && serialPortService != null) {
            String port = serialPortService.getCurrentPortPath();
            if (port != null) {
                for (int i = 0; i < mPortList.size(); i++) {
                    if (mPortList.get(i).equals(port)) {
                        binding.spinnerPort.setSelection(i);
                        break;
                    }
                }
            }
        }
    }

    // SerialPortServiceHelper.ServiceConnectionCallback 接口实现
    @Override
    public void onServiceConnected(SerialPortService service) {
        this.serialPortService = service;
        addLog("串口服务已连接", LOG_TYPE_INFO);
        
        // 注册监听器
        service.addDataListener(this);
        service.addStatusListener(this);
    }

    @Override
    public void onServiceDisconnected() {
        addLog("串口服务已断开", LOG_TYPE_INFO);
        this.serialPortService = null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        
        // ServiceHelper的生命周期会自动处理服务解绑
        // 但我们需要移除监听器
        if (serialPortService != null) {
            serialPortService.removeDataListener(this);
            serialPortService.removeStatusListener(this);
        }
    }
} 